package net.vinote.smart.platform.controller;

import java.io.IOException;
import java.io.Writer;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.comm.StringFunction;
import net.vinote.smart.platform.exception.PlatformException;
import net.vinote.smart.platform.module.database.DBManager;
import net.vinote.smart.platform.module.database.DBManagerFactory;
import net.vinote.smart.platform.module.database.bo.BizObject;
import net.vinote.smart.platform.module.database.bo.DBQuery;
import net.vinote.smart.platform.module.log.RunLogger;
import net.vinote.smart.platform.service.DWException;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.awe.layout.DataWindowList;
import net.vinote.smart.platform.service.awe.layout.ui.UILookAndFeel;
import net.vinote.smart.platform.service.bean.CodeLibrary;
import net.vinote.smart.platform.service.bean.DataWindowCatalog;
import net.vinote.smart.platform.service.bean.DataWindowLibrary;
import net.vinote.smart.platform.service.bean.DataWindowPage;
import net.vinote.smart.platform.service.dw.DataWindow;
import net.vinote.smart.platform.service.dw.DataWindowInfo;
import net.vinote.smart.platform.service.dw.component.Component;
import net.vinote.smart.platform.service.dw.handler.CommonHandler;
import net.vinote.smart.platform.service.dw.handler.HandlerPerimissionAnnotation;
import net.vinote.smart.platform.service.dw.handler.VirtualCommonHandler;
import net.vinote.smart.platform.service.dw.html.ButtonTag;
import net.vinote.smart.platform.service.util.Permission;
import net.vinote.smart.platform.service.util.Permission.PermissionUtil;
import net.vinote.smart.platform.util.JsonUtil;

import org.apache.commons.lang.math.NumberUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class DataWindowPageController {
	@RequestMapping("datawindow_page.html")
	public ModelAndView showPage(HttpServletRequest request, HttpServletResponse response) {
		String pagePath = request.getParameter("pagePath");
		DataWindowPage dwPage = SRE.getDataWindowPage(pagePath);
		if (dwPage == null) {
			throw new PlatformException("未定义页面:" + pagePath);
		}

		String style = dwPage.getDisplayStyle();
		DataWindow dw = null;
		if ("List".equals(style)) {
			dw = new DataWindowList(request);
			// 添加事件
			String eventStr = dwPage.getDatagridEvent();
			String scriptStr = dwPage.getDatagridScript();
			if (eventStr != null && eventStr.length() > 0 && scriptStr != null && scriptStr.length() > 0) {
				String[] events = dwPage.getDatagridEvent().split(",");
				String[] scripts = dwPage.getDatagridScript().split(",");
				for (int i = 0, length = events.length; i < length; i++) {
					((DataWindowList) dw).setEvent(events[i], scripts[i]);
				}
			}
			((DataWindowList) dw).setPageSize(20);
		} else if ("Info".equals(style)) {
			dw = new DataWindowInfo(request);
		}

		// 生成按钮
		String[] btnArrays;
		String buttonsStr = dwPage.getButtons();
		if (buttonsStr == null) {
			buttonsStr = "";
		}
		if (buttonsStr != null && buttonsStr.indexOf(PlatformConst.SPLIT_COMMA) > 0) {
			btnArrays = dwPage.getButtons().split(PlatformConst.SPLIT_COMMA);
		} else {
			btnArrays = new String[] { buttonsStr };
		}
		Map<String, CodeLibrary> btnMap = SRE.getCodeItems("ButtonGroup");
		String[][] btns = new String[btnArrays.length][2];
		boolean hasBtn = false;
		for (int i = 0, length = btnArrays.length; i < length; i++) {
			CodeLibrary cl = btnMap.get(btnArrays[i]);
			if (cl == null) {
				continue;
			}
			hasBtn = true;
			btns[i][0] = cl.getItemName();
			btns[i][1] = btnArrays[i] + "()";
		}
		if (hasBtn) {
			UILookAndFeel uiAction = UILookAndFeel.getInstance();
			ButtonTag[] buttons = uiAction.getButtons(btns);
			dw.addButtons(buttons, Component.ALL);
		}
		// 显示模板查询参数
		String dwParam = dwPage.getDwParam();
		String dwParamArrays[] = StringFunction.nullToBlank(dwPage.getDwParam()).split(PlatformConst.SPLIT_COMMA);
		String dwParamVal[] = new String[dwParamArrays.length];
		for (int i = 0, length = dwParamVal.length; i < length; i++) {
			dwParamVal[i] = request.getParameter(dwParamArrays[i]);
		}
		if (dwParam != null && dwParam.length() > 0) {
			dw.setParamVal(dwParamVal.length > 0 ? dwParamVal : new String[] { dwPage.getDwParam() });
		}
		dw.setDoNo(dwPage.getDoNo());

		// JS
		String js = dwPage.getScript();
		Set<String> keySet = request.getParameterMap().keySet();
		for (String key : keySet) {
			js = js.replace("${" + key + "}", request.getParameter(key));
		}

		ModelAndView mav = new ModelAndView("datawindow_page");
		try {
			mav.addObject("html", dw.getHtml());
		} catch (SQLException e) {
			e.printStackTrace();
		}
		mav.addObject("page_title",
			SRE.getSystemParameter().getSystemName() + "--" + SRE.getDataWindowCatalog(dwPage.getDoNo()).getDoName());
		mav.addObject("js", js);
		mav.addObject("pagePath", pagePath);
		mav.addObject("themes", SRE.getSystemParameter().getSysThemes());
		mav.addObject("doNo", dwPage.getDoNo());
		return mav;
	}

	@RequestMapping("datawindow_page1.html")
	public ModelAndView dataWindowPage(HttpServletRequest request, HttpServletResponse response) {
		// datawindow_page
		String pagePath = request.getParameter("pagePath");
		DataWindowPage dwPage = SRE.getDataWindowPage(pagePath);
		if (dwPage == null) {
			throw new PlatformException("未定义页面:" + pagePath);
		}
		String dwParam = dwPage.getDwParam();
		JSONObject dwDataParamJson = new JSONObject();
		String dwParamArrays[] = StringFunction.nullToBlank(dwParam).split(PlatformConst.SPLIT_COMMA);
		String dwParamVal[] = new String[dwParamArrays.length];
		for (int i = 0, length = dwParamVal.length; i < length; i++) {
			dwParamVal[i] = request.getParameter(dwParamArrays[i]);
			dwDataParamJson.put(dwParamArrays[i], request.getParameter(dwParamArrays[i]));
		}

		String doNo = dwPage.getDoNo();

		// datawindow_catalog
		DataWindowCatalog dwCatalog = SRE.getDataWindowCatalog(dwPage.getDoNo());
		// datawindow_library
		List<DataWindowLibrary> dwLibrary = SRE.getDataWindowLibrary(dwPage.getDoNo());

		JSONObject eventJson = new JSONObject();
		JSONObject codeJson = new JSONObject();
		JSONObject jsonArrayJson = new JSONObject();
		for (DataWindowLibrary lib : dwLibrary) {
			// datawindow_event
			Map<String, String> eventMap = SRE.getDataObjectEvent(doNo, lib.getFieldCode());
			if (eventMap != null && eventMap.size() >= 0) {
				eventJson.put(lib.getFieldCode(), eventMap);
			}

			// htmlsource_code
			if (PlatformConst.HtmlSource.CODE.equals(lib.getHtmlSource())) {
				String htmVal = lib.getHtmlVal();
				if (!codeJson.has(htmVal)) {
					Map<String, CodeLibrary> codeLib = SRE.getCodeItems(htmVal);
					codeJson.put(htmVal, JsonUtil.getJsonMap(codeLib));
				}
			} else if (PlatformConst.HtmlSource.JSON_ARRAY.equals(lib.getHtmlSource())) {
				String htmVal = lib.getHtmlVal();
				if (!jsonArrayJson.has(htmVal)) {
					CodeLibrary codeLib = SRE.getCodeItems("JsonArrayCode").get(htmVal);
					JSONArray array = new JSONArray(codeLib.getAttr01());
					codeJson.put(htmVal, array);
				}
			}
		}
		JSONObject htmlSourceJson = new JSONObject();
		htmlSourceJson.put(PlatformConst.HtmlSource.CODE, codeJson);
		htmlSourceJson.put(PlatformConst.HtmlSource.JSON_ARRAY, jsonArrayJson);

		// 页面按钮组
		List<CodeLibrary> pageButtons = new ArrayList<CodeLibrary>();
		String[] btnArrays;
		String buttonsStr = dwPage.getButtons();
		if (buttonsStr == null) {
			buttonsStr = "";
		}
		if (buttonsStr != null && buttonsStr.indexOf(PlatformConst.SPLIT_COMMA) > 0) {
			btnArrays = dwPage.getButtons().split(PlatformConst.SPLIT_COMMA);
		} else {
			btnArrays = new String[] { buttonsStr };
		}
		Map<String, CodeLibrary> btnMap = SRE.getCodeItems("ButtonGroup");
		for (int i = 0, length = btnArrays.length; i < length; i++) {
			CodeLibrary cl = btnMap.get(btnArrays[i]);
			if (cl == null) {
				continue;
			}
			pageButtons.add(cl);
		}

		JSONObject dataList;
		try {
			String[] paramVal = null;
			if (dwParam != null && dwParam.length() > 0) {
				paramVal = dwParamVal.length > 0 ? dwParamVal : new String[] { dwPage.getDwParam() };
			}
			dataList = getDataListJson(request, dwPage, dwCatalog, dwLibrary, paramVal);
		} catch (SQLException e) {
			dataList = new JSONObject();
			dataList.put("success", false);
			dataList.put("message", e.getLocalizedMessage());
			RunLogger.getLogger().log(e);
		}

		ModelAndView mav = new ModelAndView("datawindow_page1");
		mav.addObject("dwPage", JsonUtil.getJsonObject(dwPage));
		mav.addObject("dwCatalog", JsonUtil.getJsonObject(dwCatalog));
		mav.addObject("dwLibrary", JsonUtil.getJsonObject(dwLibrary));
		mav.addObject("dwEvent", eventJson);
		mav.addObject("htmlSource", htmlSourceJson);
		mav.addObject("pageButtons", pageButtons);
		mav.addObject("dataList", dataList);
		mav.addObject("dataParam", dwDataParamJson);
		return mav;
	}

	private JSONObject getDataListJson(HttpServletRequest request, DataWindowPage dwPage, DataWindowCatalog dwCatalog,
		List<DataWindowLibrary> dwLibrary, String[] paramVal) throws SQLException {
		CommonHandler handler;// 显示模板的handler类
		boolean isVirtual = false;
		List<BizObject> dataList = null;// 查询数据结果集
		int total = 0;// 数据总量
		String whereSql = "";
		int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 10);
		int page = NumberUtils.toInt(request.getParameter("page"), 1);

		isVirtual = VIRTUAL_FLAG.equalsIgnoreCase(dwCatalog.getMainTable());
		/** 初始化handler */
		handler = initHandlerClass(dwCatalog.getHandler(), isVirtual);
		handler.setRequest(request);
		// 是否启用了防火墙进行 权限校验
		if (SRE.getSystemParameter().getFirewall() == PlatformConst.Yes) {
			HandlerPerimissionAnnotation annotation = handler.getClass().getAnnotation(
				HandlerPerimissionAnnotation.class);
			if (annotation == null) {
				throw new PlatformException(dwCatalog.getHandler() + "未指定权限,操作存在隐患!");
			}
			Permission permission = isVirtual ? annotation.virtual() : annotation.query();
			if (permission == null || (permission.value() == null || permission.value().length == 0)
				&& (permission.ExtendedPermision() == null || permission.ExtendedPermision().length == 0)) {
				throw new PlatformException(dwCatalog.getHandler() + "未指定权限,操作存在隐患!");
			}
			if (!PermissionUtil.hasPermission(permission, request)) {
				throw new PlatformException(dwCatalog.getHandler() + "权限校验失败" + permission);
			}
		}
		// 虚表模板无需初始化数据
		if (isVirtual) {
			dataList = ((VirtualCommonHandler) handler).initDataList();
			// 统计数据量
			total = ((VirtualCommonHandler) handler).initDataCount();
		} else {
			String appendSql = "";
			List<String> fieldList = new ArrayList<String>(dwLibrary.size());
			for (DataWindowLibrary tag : dwLibrary) {
				String dataObj = StringFunction.nullToBlank(tag.getDataObj()).trim();
				if (!dataObj.equals("")) {
					fieldList.add(dataObj + "." + tag.getColField());
				}
			}
			String[] fieldArray = new String[fieldList.size()];
			fieldList.toArray(fieldArray);
			String unionTable = dwCatalog.getUnionTable();
			if (unionTable != null && "".equals(unionTable.trim())) {
				unionTable = null;
			}

			whereSql = dwCatalog.getWhereSQL() + " " + appendSql;

			// JSONObject dataParamJson = new JSONObject(
			// request.getParameter("dataParam"));
			// String dwParam = dwPage.getDwParam();
			// String dwParamArrays[] = StringFunction.nullToBlank(
			// dwPage.getDwParam()).split(PlatformConst.SPLIT_COMMA);
			// String dwParamVal[] = new String[dwParamArrays.length];
			// for (int i = 0, length = dwParamVal.length; i < length; i++) {
			// dwParamVal[i] = dataParamJson.getString(dwParamArrays[i]);
			// }
			// if (dwParam != null && dwParam.length() > 0) {
			// paramVal = dwParamVal.length > 0 ? dwParamVal
			// : new String[] { dwPage.getDwParam() };
			// }
			//
			// String dwParam = dwPage.getDwParam();
			// String dwParamArrays[] = StringFunction.nullToBlank(
			// dwPage.getDwParam()).split(PlatformConst.SPLIT_COMMA);
			// String dwParamVal[] = new String[dwParamArrays.length];
			// for (int i = 0, length = dwParamVal.length; i < length; i++) {
			// dwParamVal[i] = request.getParameter(dwParamArrays[i]);
			// }
			// if (dwParam != null && dwParam.length() > 0) {
			// paramVal = dwParamVal.length > 0 ? dwParamVal
			// : new String[] { dwPage.getDwParam() };
			// }
			DBManager bm = DBManagerFactory.getInstance(dwCatalog.getMainTable());
			DBQuery dataDuery = bm.createQuery(fieldArray, whereSql, paramVal, unionTable);
			dataDuery.setPagination(pageSize, page);

			dataList = dataDuery.getResultList();
			DBQuery query = bm.createQuery(fieldArray, whereSql, paramVal, unionTable);
			query.setQuerySql("select count(1) totalNum from (" + query.getQuerySql() + ") as countNumSQL");
			total = Integer.parseInt(query.getSingleResult("totalNum").getAttribute("totalNum"));

		}

		JSONObject respJson = new JSONObject();
		JSONObject dataJson = new JSONObject();
		respJson.put("success", true);
		dataJson.put("total", total);
		JSONArray dataArray = new JSONArray();
		for (BizObject biz : dataList) {
			dataArray.put(biz.getJSON());
		}
		dataJson.put("rows", dataArray);
		dataJson.put("page", page);
		dataJson.put("pageSize", pageSize);
		respJson.put("data", dataJson);
		return respJson;
	}

	/** 虚拟模板标识 */
	public static final String VIRTUAL_FLAG = "V";

	@RequestMapping("datawindowlist.json")
	public void getDataList(HttpServletRequest request, Writer writer) {
		String pagePath = request.getParameter("pagePath");
		DataWindowPage dwPage = SRE.getDataWindowPage(pagePath);
		if (dwPage == null) {
			throw new PlatformException("未定义页面:" + pagePath);
		}

		DataWindowCatalog dwCatalog = SRE.getDataWindowCatalog(dwPage.getDoNo());

		List<DataWindowLibrary> dwLibrary = SRE.getDataWindowLibrary(dwPage.getDoNo());
		JSONObject json;
		try {
			String[] paramVal = null;
			String dwParam = dwPage.getDwParam();
			if (!StringFunction.isBlank(dwParam)) {
				JSONObject dataParamJson = new JSONObject(request.getParameter("dataParam"));
				String dwParamArrays[] = StringFunction.nullToBlank(dwPage.getDwParam()).split(
					PlatformConst.SPLIT_COMMA);
				String dwParamVal[] = new String[dwParamArrays.length];
				for (int i = 0, length = dwParamVal.length; i < length; i++) {
					dwParamVal[i] = dataParamJson.getString(dwParamArrays[i]);
				}
				paramVal = dwParamVal.length > 0 ? dwParamVal : new String[] { dwPage.getDwParam() };
			}
			json = getDataListJson(request, dwPage, dwCatalog, dwLibrary, paramVal);
		} catch (SQLException e) {
			json = new JSONObject();
			json.put("success", false);
			json.put("message", e.getLocalizedMessage());
			RunLogger.getLogger().log(e);
		}
		try {
			writer.write(json.toString());
			writer.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private CommonHandler initHandlerClass(String handlerName, boolean virtual) {
		CommonHandler handlerClass = null;
		if (handlerName == null || "".equals(handlerName.trim())) {
			return virtual ? new VirtualCommonHandler() : new CommonHandler();
		}
		try {
			Object obj = Class.forName(handlerName).newInstance();
			if (virtual && obj instanceof VirtualCommonHandler) {
				handlerClass = (VirtualCommonHandler) obj;
			} else if (!virtual && obj instanceof CommonHandler) {
				handlerClass = (CommonHandler) obj;
			}
		} catch (Exception e) {
			RunLogger.getLogger().log(e);
		}
		if (handlerClass == null) {
			throw new DWException("无效Handler类:" + handlerName);
		}
		return handlerClass;
	}
}
